package org.mspring.mlog.web.security.action.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mspring.mlog.core.ServiceFactory;
import org.mspring.mlog.entity.security.User;
import org.mspring.mlog.web.security.SecurityUtils;
import org.mspring.mlog.web.security.action.ActionSecurity;
import org.mspring.mlog.web.security.action.rule.AccessRule;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 
 * @author Gao Youbo
 * @since 2013年9月10日
 */
public class ActionSecurityInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // TODO Auto-generated method stub
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        ActionSecurity actionSecurity = handlerMethod.getMethodAnnotation(ActionSecurity.class);
        if (actionSecurity == null) {
            return super.preHandle(request, response, handler);
        }
        Class<? extends AccessRule>[] ruleClass = actionSecurity.rules();
        boolean mustLogin = actionSecurity.mustLogin();
        if (handleMustLogin(request, response, mustLogin) && handleRules(request, response, ruleClass)) {
            return true;
        }
        response.sendError(403, "没有访问权限!");
        return false;
        // throw new AccessDeniedException(" 没有权限访问！ ");
    }

    protected boolean handleMustLogin(HttpServletRequest request, HttpServletResponse response, boolean mustLogin) {
        if (mustLogin == false) {
            return true;
        }
        User user = SecurityUtils.getCurrentUser(request);
        if (user == null) {
            return false;
        }
        return true;
    }

    protected boolean handleRules(HttpServletRequest request, HttpServletResponse response, Class<? extends AccessRule>... ruleClass) {
        if (ruleClass == null || ruleClass.length == 0) {
            return true;
        }
        boolean flag = false;
        for (Class<? extends AccessRule> clazz : ruleClass) {
            AccessRule rule = findAccessRule(clazz);
            if (rule == null) {
                continue;
            }
            if (rule.shouldProceed(request, response)) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    private AccessRule findAccessRule(Class<? extends AccessRule> ruleClass) {
        AccessRule accessRule = ServiceFactory.getBean(ruleClass);
        if (accessRule == null) {
            throw new NullPointerException(String.format("Could not find the rule %s. Have you registered it in the configuration file?", ruleClass.getName()));
        }
        return accessRule;
    }

}
